import React, { useState, useEffect, useLayoutEffect, useRef } from 'react';

const UseLayoutEffectDemo: React.FC = () => {
  const [showTooltip, setShowTooltip] = useState(false);
  const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });
  const buttonRef = useRef<HTMLButtonElement>(null);
  const tooltipRef = useRef<HTMLDivElement>(null);
  
  const [count, setCount] = useState(0);
  const [showEffect, setShowEffect] = useState(false);
  const [measurements, setMeasurements] = useState({
    clientHeight: 0,
    scrollHeight: 0,
    offsetHeight: 0
  });

  // useLayoutEffect 示例 - 同步测量 DOM
  useLayoutEffect(() => {
    if (showTooltip && buttonRef.current && tooltipRef.current) {
      const buttonRect = buttonRef.current.getBoundingClientRect();
      const tooltipRect = tooltipRef.current.getBoundingClientRect();
      
      // 计算 tooltip 位置，避免超出屏幕
      let left = buttonRect.left + (buttonRect.width - tooltipRect.width) / 2;
      let top = buttonRect.top - tooltipRect.height - 10;
      
      // 边界检查
      if (left < 10) left = 10;
      if (left + tooltipRect.width > window.innerWidth - 10) {
        left = window.innerWidth - tooltipRect.width - 10;
      }
      if (top < 10) {
        top = buttonRect.bottom + 10;
      }
      
      setTooltipPosition({ top, left });
    }
  }, [showTooltip]);

  // useLayoutEffect 示例 - 测量元素尺寸
  useLayoutEffect(() => {
    const element = document.getElementById('measure-element');
    if (element) {
      setMeasurements({
        clientHeight: element.clientHeight,
        scrollHeight: element.scrollHeight,
        offsetHeight: element.offsetHeight
      });
    }
  }, [showEffect]);

  // useEffect vs useLayoutEffect 对比
  const [effectValue, setEffectValue] = useState(0);
  const [layoutEffectValue, setLayoutEffectValue] = useState(0);
  const [domValue, setDomValue] = useState(0);

  useEffect(() => {
    console.log('useEffect 执行');
    setEffectValue(count * 2);
  }, [count]);

  useLayoutEffect(() => {
    console.log('useLayoutEffect 执行');
    setLayoutEffectValue(count * 3);
    // 这里可以安全地读取和修改 DOM
    setDomValue(document.body.clientHeight);
  }, [count]);

  // 闪烁效果示例
  const [flash, setFlash] = useState(false);
  
  useLayoutEffect(() => {
    if (flash) {
      const element = document.getElementById('flash-element');
      if (element) {
        element.style.backgroundColor = '#ff6b6b';
        element.style.transition = 'none';
        
        // 强制重排
        element.offsetHeight;
        
        element.style.transition = 'background-color 0.5s ease';
        element.style.backgroundColor = '#f8f9fa';
      }
    }
  }, [flash]);

  return (
    <div className="demo-page">
      <h1>useLayoutEffect Hook</h1>
      <p className="description">
        学习 useLayoutEffect 的使用场景，以及如何与 useEffect 区分使用
      </p>

      {/* 基本介绍 */}
      <div className="demo-section">
        <h2>useLayoutEffect vs useEffect</h2>
        <div className="comparison">
          <div className="comparison-item">
            <h3>useEffect</h3>
            <ul>
              <li>在浏览器绘制后异步执行</li>
              <li>不会阻塞页面渲染</li>
              <li>适合大多数副作用</li>
              <li>可能导致视觉闪烁</li>
            </ul>
          </div>
          <div className="comparison-item">
            <h3>useLayoutEffect</h3>
            <ul>
              <li>在 DOM 更新后、绘制前同步执行</li>
              <li>会阻塞页面渲染</li>
              <li>适合需要同步测量的场景</li>
              <li>避免视觉闪烁</li>
            </ul>
          </div>
        </div>
      </div>

      {/* 实际应用示例 */}
      <div className="demo-section">
        <h2>实际应用场景</h2>
        
        <div className="best-practices">
          <div className="practice-item">
            <h3>1. 工具提示定位</h3>
            <p>使用 useLayoutEffect 精确计算工具提示的位置</p>
            <button
              ref={buttonRef}
              onClick={() => setShowTooltip(!showTooltip)}
              style={{ margin: '2rem' }}
            >
              {showTooltip ? '隐藏' : '显示'}工具提示
            </button>
            
            {showTooltip && (
              <div
                ref={tooltipRef}
                style={{
                  position: 'fixed',
                  top: tooltipPosition.top,
                  left: tooltipPosition.left,
                  backgroundColor: '#333',
                  color: 'white',
                  padding: '10px',
                  borderRadius: '4px',
                  zIndex: 1000,
                  boxShadow: '0 2px 10px rgba(0,0,0,0.2)'
                }}
              >
                这是精确定位的工具提示！
              </div>
            )}
          </div>

          <div className="practice-item">
            <h3>2. DOM 测量</h3>
            <p>同步测量 DOM 元素的尺寸</p>
            <button onClick={() => setShowEffect(!showEffect)}>
              {showEffect ? '隐藏' : '显示'}测量元素
            </button>
            
            {showEffect && (
              <div>
                <div
                  id="measure-element"
                  style={{
                    backgroundColor: '#e9ecef',
                    padding: '20px',
                    margin: '10px 0',
                    border: '1px solid #ccc',
                    maxHeight: '100px',
                    overflow: 'auto'
                  }}
                >
                  <p>这是一个可测量的元素</p>
                  <p>包含多行文本</p>
                  <p>用于演示 DOM 测量</p>
                  <p>更多内容...</p>
                  <p>继续添加内容...</p>
                  <p>直到出现滚动条</p>
                </div>
                <div>
                  <p>clientHeight: {measurements.clientHeight}px</p>
                  <p>scrollHeight: {measurements.scrollHeight}px</p>
                  <p>offsetHeight: {measurements.offsetHeight}px</p>
                </div>
              </div>
            )}
          </div>

          <div className="practice-item">
            <h3>3. 避免视觉闪烁</h3>
            <p>使用 useLayoutEffect 同步更新 DOM，避免闪烁</p>
            <div style={{ margin: '1rem 0' }}>
              <button onClick={() => setFlash(true)}>触发闪烁效果</button>
              <div
                id="flash-element"
                style={{
                  padding: '20px',
                  margin: '10px 0',
                  border: '1px solid #ccc',
                  transition: 'background-color 0.5s ease'
                }}
              >
                点击按钮查看闪烁效果
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* 对比演示 */}
      <div className="demo-section">
        <h2>效果对比演示</h2>
        <p>观察 useEffect 和 useLayoutEffect 的执行顺序</p>
        
        <div className="counter-demo">
          <p>当前计数: {count}</p>
          <p>useEffect 结果: {effectValue}</p>
          <p>useLayoutEffect 结果: {layoutEffectValue}</p>
          <p>DOM 高度: {domValue}px</p>
          
          <div className="button-group">
            <button onClick={() => setCount(count + 1)}>增加计数</button>
            <button onClick={() => setCount(0)}>重置</button>
          </div>
        </div>
        
        <p className="note">
          💡 打开浏览器控制台查看执行顺序的日志输出
        </p>
      </div>

      {/* 使用场景总结 */}
      <div className="demo-section">
        <h2>使用场景总结</h2>
        
        <div className="best-practices">
          <div className="practice-item">
            <h3>使用 useLayoutEffect 的场景</h3>
            <ul>
              <li>需要同步读取 DOM 布局信息（如位置、尺寸）</li>
              <li>需要同步更新 DOM 以避免视觉闪烁</li>
              <li>工具提示、弹出菜单的定位</li>
              <li>动画的初始位置计算</li>
              <li>滚动位置的同步调整</li>
            </ul>
          </div>
          
          <div className="practice-item">
            <h3>避免使用 useLayoutEffect 的场景</h3>
            <ul>
              <li>网络请求（异步操作）</li>
              <li>订阅事件监听器</li>
              <li>不需要同步的操作</li>
              <li>可能影响性能的重计算</li>
            </ul>
          </div>
        </div>
      </div>

      {/* 代码示例 */}
      <div className="demo-section">
        <h2>代码示例</h2>
        
        <div className="code-example">
          <h3>useLayoutEffect 基本用法</h3>
          <pre>{`useLayoutEffect(() => {
  // 同步读取 DOM
  const rect = elementRef.current.getBoundingClientRect();
  
  // 同步更新 DOM
  elementRef.current.style.top = \`\${rect.top + 10}px\`;
  
  return () => {
    // 清理函数
  };
}, [dependencies]);`}</pre>
        </div>

        <div className="code-example">
          <h3>工具提示定位示例</h3>
          <pre>{`useLayoutEffect(() => {
  if (showTooltip && buttonRef.current) {
    const rect = buttonRef.current.getBoundingClientRect();
    
    // 计算最佳位置
    const tooltipTop = rect.top - tooltipHeight - 10;
    const tooltipLeft = rect.left + (rect.width - tooltipWidth) / 2;
    
    setTooltipPosition({ top: tooltipTop, left: tooltipLeft });
  }
}, [showTooltip]);`}</pre>
        </div>
      </div>
    </div>
  );
};

export default UseLayoutEffectDemo;